package jn.chen.utils.img;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.StreamProgress;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * @className: GetWallPuctice
 * @author: chenLin
 * @version: 1.0.0
 * @description:
 * @date: 24/12/24 024 16:12
 */
public class GetWallPuctice {

    //固定线程池
    private final static ExecutorService executor = Executors.newFixedThreadPool(10);
    /**
     * 爬取的壁纸分页网址
     */
    private final String formUrl = "https://wallpapershome.com/nature";
    /**
     * 获取的壁纸网址（用于获取文件下载链接和分辨率）
     */
    private final String mainUrl = "https://wallpapershome.com";
    /**
     * 文件保存路径
     */
    private static final String filePath = "F:\\img\\";
    /**
     * 总页数
     */
    private static Integer pageCount = 1;
    private static Integer page = 1;

    private static AtomicInteger downCount = new AtomicInteger(0);
    private static AtomicBoolean isCheckFileName = new AtomicBoolean(true);
    private static Lock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();

    public static void main(String[] args) {
        GetWallPuctice download = new GetWallPuctice();
        //已下载的文件列表
        List<String> fileNameList = Collections.synchronizedList(FileUtil.listFileNames(filePath));

        try {
            while (page <= pageCount) {
                List<String> urllist = download.getForm(page);
                System.out.println("=========================开始下载第" + page + "页==========================");
                if (page == 1) {
                    System.out.println("============================总共" + pageCount + "页============================");
                }
                //等待当前页面下载完成后才进行下一个任务
                CountDownLatch latch = new CountDownLatch(urllist.size());
                for (String url : urllist) {
                    executor.submit(() -> {
                        boolean success = false;
                        //失败重试次数
                        int retries = 3;
                        do {
                            if (success) {
                                break;
                            }
                            try {
                                String downloadUrl = download.getDownloadUrl(url);
                                String numberFileName = getNumberFileName(downloadUrl);
                                if (fileNameList.contains(numberFileName) && isCheckFileName.get()) {
                                    System.out.println(numberFileName + "  文件已下载，跳过");
                                    break;
                                } else {
                                    isCheckFileName.set(false);
                                    download.download(downloadUrl);
                                    success = true;
                                }
                                download.download(downloadUrl);
                                success = true;
                            } catch (IOException e) {
                                System.out.println("网络路径：" + url);
                                System.out.println("文件下载失败：" + e.getMessage());
                                retries--;
                                //休眠10后重试
                                try {
                                    lock.lock();
                                    //通知其他线程进行等待
                                    condition.awaitNanos(60_000_000_000L);
                                } catch (Exception ex) {
                                    System.out.println(ex.getMessage());
                                }finally {
                                    lock.unlock();
                                }
                            }
                        } while (retries > 0);
                        latch.countDown();//计数器减1
                    });
                }
                latch.await();//等待所有线程执行完
                System.out.println("第" + page + "页下载完成");
                page++;
                Thread.sleep(RandomUtil.randomInt(1000, 1500));
            }
        } catch (Exception e) {
            System.out.println("文件下载失败：" + e.getMessage());
            e.printStackTrace();
        } finally {
            executor.shutdown();
            System.out.println("============所有文件下载完成,本次任务成功下载" + downCount.get() + "个文件========");
        }
    }


    public List<String> getForm(Integer pageNum) throws IOException {
        String url = formUrl;
        if (Objects.nonNull(pageNum)) {
            url = formUrl + "?page=" + pageNum;
        }
        Connection connect = Jsoup.connect(url);
        connect.header("Cookie", "sid=g4m2ugp3v0sicdutrpqeepeqa1; screen-width=1440; screen-height=900; ratio=2; window-width=1392; col-width=1115; window-height=744; FCNEC=%5B%5B%22AKsRol_46hf2y-AJJMJjAiq0OgWf0wejs54kaJMdEnCoI9yKSQPj6AOgAgEB9oidBjSxbXtAMX58lbRNiBUaM_4v3DLqN2o1hxYouVGtBgYBjoEZIlzHd1hhNhXe_-RKSylBcQnBlysPs5cujvl6p2tJcUIHEgX8zA%3D%3D%22%5D%5D");
        connect.header("Host", "wallpapershome.com");
        connect.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0");
        Document doc = connect.get();
        // 提取所有链接
        Elements links = doc.select("a[href]");
        List<String> result = new ArrayList<>();
        for (Element link : links) {
            String href = link.attr("href");
            if (StrUtil.isNotBlank(href) && href.endsWith(".html")) {
                //下载页面
                result.add(mainUrl + href);
            } else if (StrUtil.isNotBlank(href) && href.startsWith("?page")) {
                int num = Integer.parseInt(href.substring(6));
                pageCount = pageCount < num ? num : pageCount;
            }
        }
        return result;
    }

    /**
     * 获取最高分辨率的壁纸下载链接
     *
     * @return
     * @throws IOException
     * @Param url
     */
    private String getDownloadUrl(String url) throws IOException {
        Connection connect = Jsoup.connect(url);
        connect.header("Cookie", "sid=g4m2ugp3v0sicdutrpqeepeqa1; screen-width=1440; screen-height=900; ratio=2; FCNEC=%5B%5B%22AKsRol8iocKLTfJ3-7NEGMVingOM01ugKcNMT6KJgW7mBKWkdyKrX4nFYMvemNKhehcHRa_WEev2BEc7SYo0mloS-q1g0HF_AV6RB4n_YPQx9Q23ZHR_F3TuBMUJ0Em3K41uJ1nWPVtn93l4f-MPJnIaHa3b0hJH0w%3D%3D%22%5D%5D; window-width=1396; window-height=750; col-width=1118");
        connect.header("Host", "wallpapershome.com");
        connect.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0");
        Document doc = connect.get();
        List<String> links = new ArrayList<>();
        doc.select("a[href]").forEach(link -> links.add(link.attr("href")));
        List<String> paragraphs = new ArrayList<>();
        doc.select("p").forEach(paragraph -> paragraphs.add(paragraph.text()));
        int max = 0;
        String maxRatio = "";
        String maxRatio2 = "";
        for (String paragraph : paragraphs) {
            String[] s = paragraph.split(" ");
            if (s.length > 1 && s[1].contains("x")) {
                String[] xes = s[1].split("x");
                if (xes.length > 1) {
                    String x = xes[0];
                    if (x.matches("\\d+") && max < Integer.parseInt(x) && links.stream().anyMatch(link -> link.contains(s[1]))) {
                        max = Integer.parseInt(x);
                        maxRatio = s[1];
                        maxRatio2 = s[0];
                    }
                }
            }
        }
//        System.out.println("最大分辨率：" + maxRatio2 + " " + maxRatio);
        String finalMaxRatio = maxRatio;
        Optional<String> first = links.stream().filter(link -> StrUtil.isNotBlank(link) && link.contains(finalMaxRatio)).findFirst();
        return first.map(s -> mainUrl + s).orElse("");
    }

    private void download(String url) throws IOException {
        if (StrUtil.isBlank(url)) {
            return;
        }
        String fileName = getFileName(url);
        //超时时间5分钟
        try {
            HttpUtil.downloadFile(url, FileUtil.file(filePath + fileName), 1000 * 60 * 5, new StreamProgress() {
                @Override
                public void start() {
                    System.out.println(Thread.currentThread().getName() + ": " + fileName + "开始下载。。。。");
                }

                @Override
                public void progress(long l) {

                }

                @Override
                public void finish() {
                    downCount.incrementAndGet();
                    System.out.println(Thread.currentThread().getName() + ": " + fileName + " 下载完成！");
                }
            });
        } catch (Exception e) {
            System.err.println(Thread.currentThread().getName() + ": " + fileName + " 下载失败！");
        }
    }


    private static String getFileName(String url) {
        return url.substring(url.lastIndexOf("/") + 1);
    }

    private static String getNumberFileName(String url) {
        String[] split = url.split("-");
        String fileName;
        if (split.length > 1) {
            fileName = split[split.length - 1];
        } else {
            fileName = url.substring(url.lastIndexOf("/") + 1);
        }
        return fileName;
    }
}
